﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;

namespace ConsoleResult
{
    class Reader
    {
        static Dictionary<string, string> truth;
        static Dictionary<string, string> prediction;
        static SortedDictionary<string, SortedDictionary<string, int>> confusionmatrix;
        static List<string> alllabels;

        static Dictionary<string, Dictionary<string, int>> truthcount; // <user,<label,count>>
        static Dictionary<string, Dictionary<string, int>> predcount;
        static Dictionary<string, Dictionary<string, int>> predtruthcount;        

        static int sharpnumber = -1;
        static string datatype = "A";
        static string percent = "A";
        static int iternum = 1;
        static string labeltype = "1";
        
        static string midfix = "-L";

        static int maxiterationnumber = 10;
        static int maxinferenceNumber = 100;

        public static void ReadAndShowBewell(string ins,string datatype)
        {
            int iternum = int.Parse(ins);

            string path = System.IO.Directory.GetCurrentDirectory() + "\\netkit-run-0.log";
            string rpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-tmp.txt";
            StreamReader reader = new StreamReader(path);
            StreamWriter writer = new StreamWriter(rpath, !(iternum == 1));
            
            string line;
            double basic = 0, min = 2, max = -1, last = -1;
            int runs = 0;
            while ((line = reader.ReadLine()) != null)
            {
                if (line.IndexOf("iteration--1") > -1)
                {
                    if (min <= 1)
                    {
                        runs++;
                        writer.Write(iternum + " " + basic.ToString("0.0000"));
                        writer.Write(" " + min.ToString("0.0000"));
                        writer.Write(" " + max.ToString("0.0000"));
                        writer.WriteLine(" " + last.ToString("0.0000"));

                        last = max = -1;
                        min = 2;
                    }
                    basic = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                }
                else if (line.IndexOf("iteration-") > -1)
                {
                    last = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                    if (last < min)
                        min = last;
                    if (last > max)
                        max = last;
                }
                else
                    continue;
            }

            writer.Write(iternum + " " + basic.ToString("0.0000"));
            writer.Write(" " + min.ToString("0.0000"));
            writer.Write(" " + max.ToString("0.0000"));
            writer.WriteLine(" " + last.ToString("0.0000"));

            writer.Close();
            reader.Close();

            if (iternum == maxiterationnumber)
            {
                reader = new StreamReader(rpath);
                List<double> basics = new List<double>(), mins = new List<double>(), maxs = new List<double>(), lasts = new List<double>();
                double bsum = 0, minsum = 0, maxsum = 0, lastsum = 0;
                int size = 0;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splits = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    bsum += double.Parse(splits[1]);
                    minsum += double.Parse(splits[2]);
                    maxsum += double.Parse(splits[3]);
                    lastsum += double.Parse(splits[4]);
                    size++;
                }
                bsum /= size;
                minsum /= size;
                maxsum /= size;
                lastsum /= size;

                writer = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-final.txt");
                writer.WriteLine(bsum.ToString("0.0000") + " " + minsum.ToString("0.0000") + " " + maxsum.ToString("0.0000") + " " + lastsum.ToString("0.0000"));
                writer.Close();
                reader.Close();
            }
        }

        public static void ReadAndShowFood(string ins, string dt, string lt, string pc,string im)
        {
            iternum = int.Parse(ins);
            datatype = dt;               
            labeltype = lt;
            percent = pc;
            if (im == "g")
                maxinferenceNumber = 2200;
            else if (im=="r")
                maxinferenceNumber = 100;
            else 
                maxinferenceNumber = 1001;

            string path = System.IO.Directory.GetCurrentDirectory() + "\\netkit-run-0.log";
            string rpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-tmp.txt";
            StreamReader reader = new StreamReader(path);
            StreamWriter writer = new StreamWriter(rpath, !(iternum == 1));            

            string line;
            double basic = 0, min = 2, max = -1, last = -1;
            int runs = 0;
            while ((line = reader.ReadLine()) != null)
            {
                if (line.IndexOf("iteration--1") > -1)
                {
                    if (min <= 1)
                    {
                        runs++;
                        writer.Write(iternum + " " + basic.ToString("0.0000"));
                        writer.Write(" " + min.ToString("0.0000"));
                        writer.Write(" " + max.ToString("0.0000"));
                        writer.WriteLine(" " + last.ToString("0.0000"));                       

                        last = max = -1;
                        min = 2;
                    }
                    basic = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                }
                else if (line.IndexOf("iteration-") > -1)
                {
                    last = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                    if (last < min)
                        min = last;
                    if (last > max)
                        max = last;
                }
                else
                    continue;
            }

            writer.Write(iternum + " " + basic.ToString("0.0000"));
            writer.Write(" " + min.ToString("0.0000"));
            writer.Write(" " + max.ToString("0.0000"));
            writer.WriteLine(" " + last.ToString("0.0000"));            
            
            writer.Close();
            reader.Close();

            if (iternum == maxiterationnumber)
            {
                reader = new StreamReader(rpath);
                List<double> basics = new List<double>(), mins = new List<double>(), maxs = new List<double>(), lasts = new List<double>();
                double bsum = 0, minsum = 0, maxsum = 0, lastsum = 0;
                List<double> localAccs = new List<double>(), netAccs = new List<double>();
                
                int size = 0;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splits = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    bsum += double.Parse(splits[1]);
                    minsum += double.Parse(splits[2]);
                    maxsum += double.Parse(splits[3]);
                    lastsum += double.Parse(splits[4]);
                    localAccs.Add(double.Parse(splits[1]));
                    netAccs.Add(double.Parse(splits[4]));
                    size++;
                }
                bsum /= size;
                minsum /= size;
                maxsum /= size;
                lastsum /= size;

                writer = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-final.txt", true);                
                //writer.Write(labels[int.Parse(labeltype)] + " " + percent + "/4: ");
                writer.WriteLine(bsum.ToString("0.0000") + " " /*+ minsum.ToString("0.0000") + " " + maxsum.ToString("0.0000") + " " */+ lastsum.ToString("0.0000"));
                writer.Close();
                reader.Close();

                StreamWriter errorWriter = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-Error.txt", true);
                List<double> localAbove = new List<double>(), localBelow = new List<double>(), netAbove = new List<double>(), netBelow = new List<double>();
                foreach (double acc in localAccs)
                {
                    if (acc >= bsum)
                        localAbove.Add(acc - bsum);
                    if (acc <= bsum)
                        localBelow.Add(bsum - acc);
                }
                foreach (double acc in netAccs)
                {
                    if (acc >= lastsum)
                        netAbove.Add(acc - lastsum);
                    if (acc <= lastsum)
                        netBelow.Add(lastsum - acc);
                }
                errorWriter.WriteLine(standardError(localAccs).ToString("0.00000") + " " + standardError(netAccs).ToString("0.00000"));//localbelow, localabove, netbelow, netabove
                
                errorWriter.Close();
            }
        }

        public static void ReadAndShowTrans(string[] args)
        {            
            iternum = int.Parse(args[0]);
            datatype = args[1];

            string path = System.IO.Directory.GetCurrentDirectory() + "\\netkit-run-0.log";
            string rpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-tmp.txt";
            StreamReader reader = new StreamReader(path);
            StreamWriter writer = new StreamWriter(rpath, !(iternum == 1));

            string line;
            double basic = 0, min = 2, max = -1, last = -1;
            int runs = 0;
            while ((line = reader.ReadLine()) != null)
            {
                if (line.IndexOf("iteration--1") > -1)
                {
                    if (min <= 1)
                    {
                        runs++;
                        writer.Write(iternum + " " + basic.ToString("0.0000"));
                        writer.Write(" " + min.ToString("0.0000"));
                        writer.Write(" " + max.ToString("0.0000"));
                        writer.WriteLine(" " + last.ToString("0.0000"));

                        last = max = -1;
                        min = 2;
                    }
                    basic = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                }
                else if (line.IndexOf("iteration-") > -1)
                {
                    last = double.Parse(line.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries)[1]);
                    if (last < min)
                        min = last;
                    if (last > max)
                        max = last;
                }
                else
                    continue;
            }

            writer.Write(iternum + " " + basic.ToString("0.0000"));
            writer.Write(" " + min.ToString("0.0000"));
            writer.Write(" " + max.ToString("0.0000"));
            writer.WriteLine(" " + last.ToString("0.0000"));

            writer.Close();
            reader.Close();            
            if (iternum == maxiterationnumber)
            {            
                reader = new StreamReader(rpath);
                List<double> basics = new List<double>(), mins = new List<double>(), maxs = new List<double>(), lasts = new List<double>();
                double bsum = 0, minsum = 0, maxsum = 0, lastsum = 0;
                int size = 0;
                while ((line = reader.ReadLine()) != null)
                {
                    string[] splits = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    bsum += double.Parse(splits[1]);
                    minsum += double.Parse(splits[2]);
                    maxsum += double.Parse(splits[3]);
                    lastsum += double.Parse(splits[4]);
                    size++;
                }
                bsum /= size;
                minsum /= size;
                maxsum /= size;
                lastsum /= size;

                writer = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-Result-final.txt");
                writer.WriteLine(bsum.ToString("0.0000") + " " + minsum.ToString("0.0000") + " " + maxsum.ToString("0.0000") + " " + lastsum.ToString("0.0000"));
                writer.Close();
                reader.Close();
            }
        }

        private static double standardError(List<double> data)
        {
            double avg = data.Average();
            double sum = 0;
            foreach (double d in data)
            {
                sum += (d - avg) * (d - avg);
            }
            return Math.Sqrt(sum / data.Count) / Math.Sqrt(data.Count);
        }

        public static void ParseDetailResults()
        {
            midfix = "-L";
            string local = "\\zzz-out.0.predict";
            readTruth();
            readPrediction(local);

            midfix = "-N";
            string network = "\\zzz-out.predict";
            readTruth();
            readPrediction(network);

            delete();
            if (iternum == maxiterationnumber)
            {
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict-AggUser.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict-AggUser.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict-AggLabel.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Predict-AggLabel.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Matrix.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-L" + "-Matrix.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict-AggUser.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict-AggUser.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict-AggLabel.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Predict-AggLabel.txt");
                if (System.IO.File.Exists(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Matrix.txt"))
                    System.IO.File.Delete(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-N" + "-Matrix.txt");
            }
        }

        private static void readPrediction(string f)
        {
            string path = System.IO.Directory.GetCurrentDirectory() + f;

            StreamReader reader = new StreamReader(path);
            string line;

            prediction = new Dictionary<string, string>();
            while ((line = reader.ReadLine()) != null)
            {
                if (line.IndexOf("#") > -1)
                {
                    if (prediction.Count > 0)
                    {
                        count();
                        outputConMatrix();
                        NoAggregation();
                        AggregationOnUser();
                        AggregationOnLabel();
                        AggregationOnTime();
                        
                    }
                    prediction = new Dictionary<string, string>();

                    sharpnumber = int.Parse(line.Substring(line.IndexOf("#") + 1, 1));

                    Dictionary<string, Dictionary<string, int>> tmp = new Dictionary<string, Dictionary<string, int>>();
                    foreach (string user in predcount.Keys)
                    {
                        Dictionary<string, int> labelcount = predcount[user];
                        tmp.Add(user, new Dictionary<string, int>());
                        foreach (string label in labelcount.Keys)
                        {
                            tmp[user].Add(label, 0);
                        }
                    }
                    predcount = tmp;

                    tmp = new Dictionary<string, Dictionary<string, int>>();                    
                    foreach (string user in predtruthcount.Keys)
                    {
                        Dictionary<string, int> labelcount = predtruthcount[user];
                        tmp.Add(user, new Dictionary<string, int>());
                        foreach (string label in labelcount.Keys)
                        {
                            tmp[user].Add(label, 0);
                        }                        
                    }
                    predtruthcount = tmp;
                }
                else
                {
                    string[] splits = line.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    string label = "";
                    double confidence = -1;
                    for (int i = 1; i < splits.Length; i++)
                    {
                        string[] pairs = splits[i].Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);

                        if (double.Parse(pairs[1]) >= confidence)
                        {
                            label = pairs[0];
                            confidence = double.Parse(pairs[1]);
                        }
                    }
                    prediction.Add(splits[0], label);                    
                }
            }

            if (prediction.Count > 0)
            {
                count();
                outputConMatrix();
                NoAggregation();
                AggregationOnLabel();
                AggregationOnUser();
                AggregationOnTime();
            }

            reader.Close();
        }

        private static void readTruth()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + "-truth.csv";
            StreamReader reader = new StreamReader(path);

            string line;
            truth = new Dictionary<string, string>();
            truthcount = new Dictionary<string, Dictionary<string, int>>();
            predcount = new Dictionary<string, Dictionary<string, int>>();
            predtruthcount = new Dictionary<string, Dictionary<string, int>>();            
            confusionmatrix = new SortedDictionary<string, SortedDictionary<string, int>>();
            alllabels = new List<string>();

            while ((line = reader.ReadLine()) != null)
            {
                string[] splits = line.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                string label = splits[splits.Length - 1];
                string user = splits[0].Split(new char[] { 'F' }, StringSplitOptions.RemoveEmptyEntries)[0];

                truth.Add(splits[0], label);
                
                Dictionary<string, int> label2count;
                if (!truthcount.TryGetValue(user, out label2count))
                {
                    label2count = new Dictionary<string, int>();
                    truthcount.Add(user, label2count);
                    predcount.Add(user, new Dictionary<string, int>());
                    predtruthcount.Add(user, new Dictionary<string, int>());                    
                }

                int c;
                if (!label2count.TryGetValue(label, out c))
                {
                    label2count.Add(label, 1);
                    predcount[user].Add(label, 0);
                    predtruthcount[user].Add(label, 0);                    
                }
                else
                    label2count[label]++;

                if (!alllabels.Contains(label))
                    alllabels.Add(label);
                truthcount[user] = label2count;
            }
            reader.Close();

            foreach (string la in alllabels)
            {
                confusionmatrix.Add(la, new SortedDictionary<string, int>());
                foreach (string lb in alllabels)
                    confusionmatrix[la].Add(lb, 0);
            }
        }

        private static void count()
        {
            Dictionary<string, string>.Enumerator predenu = prediction.GetEnumerator();

            bool right;            
            while (predenu.MoveNext())
            {
                confusionmatrix[truth[predenu.Current.Key]][predenu.Current.Value]++;
                right = truth[predenu.Current.Key] == predenu.Current.Value;
                //Console.WriteLine("R " + right + " " + truth[predenu.Current.Key]+" "+ predenu.Current.Value);
                string user = predenu.Current.Key.Split(new char[] { 'F' }, StringSplitOptions.RemoveEmptyEntries)[0];

                if (right)
                {
                    predcount[user][predenu.Current.Value]++;                    
                }

                predtruthcount[user][truth[predenu.Current.Key]]++;                
            }            
        }

        private static void NoAggregation()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict.txt";
            StreamWriter writer = new StreamWriter(path, true);
            Dictionary<string, Dictionary<string, int>>.Enumerator userenu = predcount.GetEnumerator();

            writer.WriteLine(percent + "/4");
            double rightnum = 0;
            while (userenu.MoveNext())
            {
                writer.Write(userenu.Current.Key + ":");

                Dictionary<string, int>.Enumerator countenu = predcount[userenu.Current.Key].GetEnumerator();
                while (countenu.MoveNext())
                {
                    writer.Write(countenu.Current.Key + " " + countenu.Current.Value + " " + predtruthcount[userenu.Current.Key][countenu.Current.Key] + " " + truthcount[userenu.Current.Key][countenu.Current.Key] + ",");
                    rightnum += countenu.Current.Value;
                }
                writer.WriteLine();
            }
            writer.WriteLine(rightnum / prediction.Count);
            writer.WriteLine();

            writer.Close();

            if (iternum == maxiterationnumber)
            {
                Console.WriteLine("No Agg");
                #region  noAgg                
                
                Dictionary<string, Dictionary<string, int>> finalPCount = new Dictionary<string, Dictionary<string, int>>();
                Dictionary<string, Dictionary<string, int>> finalBCount = new Dictionary<string, Dictionary<string, int>>();
                Dictionary<string, int> flpcount, flbcount;
                string fpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-F.txt";
                StreamReader reader = new StreamReader(path);
                writer = new StreamWriter(fpath, true);
                writer.WriteLine(datatype + " " + labels[int.Parse(labeltype)] + " " + percent + "/4");

                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (!(line.IndexOf(":") > -1))
                        continue;

                    string[] splits = line.Split(new char[]{':'},StringSplitOptions.RemoveEmptyEntries);

                    if (!finalPCount.TryGetValue(splits[0], out flpcount))
                    {
                        flpcount = new Dictionary<string, int>();
                        finalPCount.Add(splits[0], flpcount);
                    }
                    if (!finalBCount.TryGetValue(splits[0], out flbcount))
                    {
                        flbcount = new Dictionary<string, int>();
                        finalBCount.Add(splits[0], flbcount);
                    }

                    string[] labelss = splits[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < labelss.Length; i++)
                    {
                        string[] parts = labelss[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        if (parts.Length < 3)
                            continue;
                        int t;
                        if (!flpcount.TryGetValue(parts[0], out t))
                            flpcount.Add(parts[0], 0);
                        if (!flbcount.TryGetValue(parts[0], out t))
                            flbcount.Add(parts[0], 0);

                        flpcount[parts[0]] += int.Parse(parts[1]);
                        flbcount[parts[0]] += int.Parse(parts[2]);
                    }

                    finalPCount[splits[0]] = flpcount;
                    finalBCount[splits[0]] = flbcount;
                }

                double ratio = 0, pnum = 0, bnum = 0;
                foreach (string key in finalPCount.Keys)
                {
                    flpcount = finalPCount[key];
                    flbcount = finalBCount[key];
                    writer.Write(key + ":");
                    foreach (string lk in flpcount.Keys)
                    {
                        writer.Write(lk + " " + flpcount[lk] + " " + flbcount[lk] + ",");
                        pnum += flpcount[lk];
                        bnum += flbcount[lk];
                    }
                    writer.WriteLine();
                }
                ratio = pnum / bnum;
                writer.WriteLine(pnum + "/" + bnum + "=" + ratio);
                writer.WriteLine();
                writer.Close();
                reader.Close();
                #endregion

                Console.WriteLine("AggUser");
                #region AggUser
                fpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-AggUser-F.csv";
                writer = new StreamWriter(fpath,true);
                writer.WriteLine(datatype + " " + labels[int.Parse(labeltype)] + " " + percent + "/4");
                double ppnum = 0, bbnum = 0;

                List<double> userRatio = new List<double>();
                double matchUser = 0, totalUser = 0;

                foreach (string user in finalPCount.Keys)
                {
                    flpcount = finalPCount[user];
                    flbcount = finalBCount[user];
                    writer.Write(user + ",");
                    ppnum = 0; bbnum = 0;

                    int labelcount = 0;
                    double labelsum = 0;
                    foreach (string label in flpcount.Keys)
                    {
                        ppnum += flpcount[label];
                        bbnum += flbcount[label];

                        if (flbcount[label] != 0)
                        {
                            labelcount++;
                            labelsum += (double)flpcount[label] / (double)flbcount[label];
                        }
                    }
                    //writer.Write((labelcount == 0 ? "0" : (labelsum / labelcount).ToString("0.000")) + "; ");
                    userRatio.Add(labelcount == 0 ? 0 : labelsum / labelcount);
                    matchUser += bigThreeMatch(flpcount, flbcount);
                    totalUser++;
                    if (bbnum == 0 && ppnum > 0)
                        throw new Exception("ppnum / bbnum = " + ppnum + " " + bbnum);
                    if (bbnum == 0)
                        writer.WriteLine(0);
                    else
                        writer.WriteLine(/*ppnum + "/" + bbnum + "=" + */((double)ppnum / (double)bbnum).ToString("0.000"));
                }
                writer.WriteLine(userRatio.Average().ToString("0.000") + " ; " + pnum + "/" + bnum + "=" + ratio + " ; " + (matchUser / totalUser).ToString("0.000"));
                writer.WriteLine();
                writer.Close();
                #endregion

                Console.WriteLine("AggLabel");
                #region AggLabel
                fpath = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-AggLabel-F.txt";
                writer = new StreamWriter(fpath, true);
                writer.WriteLine(datatype + " " + labels[int.Parse(labeltype)] + " " + percent + "/4");
                Dictionary<string, double> rightlabel2count = new Dictionary<string, double>(), backlabel2count = new Dictionary<string, double>();
                foreach (string key in finalPCount.Keys)
                {
                    flpcount = finalPCount[key];
                    flbcount = finalBCount[key];                    
                   
                    foreach (string lk in flpcount.Keys)
                    {
                        double tmp;
                        if (!rightlabel2count.TryGetValue(lk, out tmp))
                        {
                            rightlabel2count.Add(lk, 0);
                        }
                        if (!backlabel2count.TryGetValue(lk, out tmp))
                        {
                            backlabel2count.Add(lk, 0);
                        }
                        rightlabel2count[lk] += flpcount[lk];
                        backlabel2count[lk] += flbcount[lk];
                    }                    
                }
                foreach (string lk in rightlabel2count.Keys)
                {
                    writer.Write(lk + " " + rightlabel2count[lk] + " " + backlabel2count[lk] + ",");                 
                }
                writer.WriteLine();
                foreach (string lk in rightlabel2count.Keys)
                {                 
                    writer.WriteLine(((double)rightlabel2count[lk] / (double)backlabel2count[lk]).ToString("0.0000"));
                }                
                writer.WriteLine(pnum + "/" + bnum + "=" + ratio.ToString("0.0000"));                
                writer.WriteLine();
                writer.Close();
                #endregion

                Console.WriteLine("Matrix");
                #region Matrix
                path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Matrix.txt";
                reader = new StreamReader(path);
                Dictionary<string, Dictionary<string, int>> finalmatrix = new Dictionary<string, Dictionary<string, int>>();
                foreach (string la in alllabels)
                {
                    finalmatrix.Add(la, new Dictionary<string, int>());
                    
                    foreach (string lb in alllabels)
                    {
                        finalmatrix[la].Add(lb, 0);
                    }
                }

                while ((line = reader.ReadLine()) != null)
                {
                    if (!(line.IndexOf(":") > -1))
                        continue;

                    string[] splits = line.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
                    string truth = splits[0];
                    string[] predictresults = splits[1].Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    for (int i = 0; i < predictresults.Length; i++)
                    {
                        finalmatrix[truth][alllabels.ElementAt(i)] += int.Parse(predictresults[i]);
                    }
                }
                reader.Close();

                writer = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Matrix-F.csv", true);
                writer.WriteLine(datatype + " " + labels[int.Parse(labeltype)] + " " + percent + "/4");
                writer.Write(" ");
                foreach (string label in alllabels)
                    writer.Write("," + label);
                writer.WriteLine();

                foreach (string truth in alllabels)
                {

                    writer.Write(truth);
                    int sum = 0;
                    int correct = finalmatrix[truth][truth];
                    foreach (string label in alllabels)
                    {
                        writer.Write("," + finalmatrix[truth][label]);
                        sum += finalmatrix[truth][label];
                    }
                    writer.WriteLine(",(" + correct + "/" + sum + " correct)");
                }
                writer.Close();
                #endregion
            }
        }

        private static int bigThreeMatch(Dictionary<string, int> flpcount, Dictionary<string, int> flbcount)
        {
            List<string> flpbt = getBigThree(flpcount);
            List<string> flbbt = getBigThree(flbcount);

            for (int i = 0; i < Math.Min(flpbt.Count, flbbt.Count); i++)
            {
                if (flpbt[i] != flbbt[i])
                    return 0;
            }
            return 1;
        }

        private static List<string> getBigThree(Dictionary<string, int> stat)
        {
            SortedList<Tuple<int, string>, string> reversetable = new SortedList<Tuple<int, string>, string>();
            foreach (string labelkey in stat.Keys)
            {
                reversetable.Add(new Tuple<int, string>(-stat[labelkey], labelkey), labelkey);
                if (reversetable.Count > 4)
                    reversetable.RemoveAt(4);
            }
            List<string> ret = new List<string>(reversetable.Select(a=>a.Value));            
            
            return ret;
        }

        private static void AggregationOnUser()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-AggUser.txt";
            StreamWriter writer = new StreamWriter(path, true);
            Dictionary<string, Dictionary<string, int>>.Enumerator userenu = predcount.GetEnumerator();

            double rightnum = 0;
            while (userenu.MoveNext())
            {
                //writer.Write(userenu.Current.Key + ":");

                Dictionary<string, int>.Enumerator countenu = predcount[userenu.Current.Key].GetEnumerator();
                double rn = 0, backnum = 0;
                while (countenu.MoveNext())
                {
                    rightnum += countenu.Current.Value;
                    rn += countenu.Current.Value;
                    backnum += predtruthcount[userenu.Current.Key][countenu.Current.Key];
                }
                writer.WriteLine(backnum == 0 ? 0 : rn / backnum);
            }
            writer.WriteLine(rightnum / prediction.Count);
            writer.WriteLine();

            writer.Close();
        }

        private static void AggregationOnLabel()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-AggLabel.txt";
            StreamWriter writer = new StreamWriter(path, true);
            Dictionary<string, Dictionary<string, int>>.Enumerator userenu = predcount.GetEnumerator();

            Dictionary<string, double> rightlabel2count = new Dictionary<string, double>(), backlabel2count = new Dictionary<string, double>();
            double rightnum = 0;
            
            while (userenu.MoveNext())
            {
                Dictionary<string, int>.Enumerator countenu = predcount[userenu.Current.Key].GetEnumerator();
                while (countenu.MoveNext())
                {
                    string key = countenu.Current.Key;                   
                    
                    double tmp;
                    if (!rightlabel2count.TryGetValue(key, out tmp))
                    {
                        rightlabel2count.Add(key,0);
                    }
                    if (!backlabel2count.TryGetValue(key, out tmp))
                    {
                        backlabel2count.Add(key, 0);
                    }

                    rightlabel2count[key] += countenu.Current.Value;
                    backlabel2count[key] += predtruthcount[userenu.Current.Key][countenu.Current.Key];

                    rightnum += countenu.Current.Value;
                }                
            }

            foreach (string key in rightlabel2count.Keys)
            {
                writer.Write(key + " " + rightlabel2count[key] + " " + backlabel2count[key] + ",");
            }
            writer.WriteLine();
            writer.WriteLine(rightnum / prediction.Count);
            writer.WriteLine();

            writer.Close();
        }
        
        private static void AggregationOnTime()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Predict-AggTimeW.txt";
            StreamWriter writer = new StreamWriter(path, true);

            List<double> windowAccuracy = new List<double>();
            int windowLength = 10;
            int collaps = 5;

            for (int i = 0; i < prediction.Count - collaps; i += collaps)
            {
                double t = 0;
                for (int j = 0; (j < windowLength && i + j < prediction.Count); j++)
                {
                    KeyValuePair<string, string> pair = prediction.ElementAt(i + j);
                    string truelbl = truth[pair.Key];
                    if (truelbl == pair.Value)
                        t++;
                }
                writer.WriteLine((t / windowLength).ToString("0.0000"));
            }            
            writer.Close();
        }

        private static void outputConMatrix()
        {
            string path = System.IO.Directory.GetCurrentDirectory() + "\\" + datatype + midfix + "-Matrix.txt";
            StreamWriter writer = new StreamWriter(path, true);

            writer.Write("\t");
            foreach (string label in alllabels)
                writer.Write(label + "\t");            
            writer.WriteLine();

            foreach (string truth in alllabels)
            {

                writer.Write(truth + ":\t");
                foreach (string label in alllabels)
                {
                    writer.Write(confusionmatrix[truth][label] + "\t");
                }
                writer.WriteLine();
            }
            writer.Close();
        }

        private static void delete()
        {
            string path = System.IO.Directory.GetCurrentDirectory();
            System.IO.File.Delete(path + "\\zzz-out.predict");
            for (int i = 0; i < maxinferenceNumber; i++)
            {
                string fp = path + "\\zzz-out." + i + ".predict";
                if (System.IO.File.Exists(fp))
                    System.IO.File.Delete(fp);
            }
        }

        static string[] labels = new string[] { "Calories", "Carbs", "Fat", "Protein", "Dish_combo", "high_calories", "cal_level" };
    }
}